/*
 * 两栈共享空间
 */

#include <stdio.h>
#include <string.h>


#define STACK_SIZE  20


/* type */
struct Student {
    int id;
    char name[100];
    int age;
    char sex;
};
typedef struct Student ElemType;
//typedef int ElemType;


/*
 *
 */
struct double_stack {
    ElemType data[STACK_SIZE];
    int top1;
    int top2;
};
typedef struct double_stack stack_t;




void
init_stack(stack_t *stack)
{
    memset(stack, 0, sizeof(stack_t));
    stack->top1 = -1;
    stack->top2 = STACK_SIZE;
}

void
clear_stack(stack_t *stack)
{
    init_stack(stack);
}

int
get_stack1_length(stack_t *stack)
{
    return stack->top1 + 1;
}

int
get_stack2_length(stack_t *stack)
{
    return STACK_SIZE - stack->top2;
}


int
is_stack1_empty(stack_t *stack)
{
    return stack->top1 == -1;
}

int
is_stack2_empty(stack_t *stack)
{
    return stack->top2 == STACK_SIZE;
}

int
is_stack_full(stack_t *stack)
{
    return (stack->top1 + 1 >= stack->top2);
}



int
get_stack1_top_item(stack_t *stack, ElemType *item)
{
    if (stack->top1 == -1)
        return -1;

    *item = stack->data[stack->top1];

    return 0;
}

int
get_stack2_top_item(stack_t *stack, ElemType *item)
{
    if (stack->top2 == STACK_SIZE)
        return -1;

    *item = stack->data[stack->top2];

    return 0;
}


/*
 *
 */
int
push(stack_t *stack, ElemType *item, int stack_num)
{
    /* if full */
    if (stack->top1 + 1 >= stack->top2)
        return -1;

    if (stack_num == 1)
        stack->data[++stack->top1] = *item;
    else if (stack_num == 2)
        stack->data[--stack->top2] = *item;

    return 0;
}

/*
 *
 */
int
pop(stack_t *stack, ElemType *item, int stack_num)
{
    if (stack_num == 1)
    {
        /* if empty */
        if (stack->top1 == -1)
            return -1;

        *item = stack->data[stack->top1--];
    }
    else if (stack_num ==2)
    {
        /* if empty */
        if (stack->top2 == STACK_SIZE)
            return -1;

        *item = stack->data[stack->top2++];
    }

    return 0;
}





/******************************************************************************/


int
main(void)
{
    stack_t stack;

    int i, ret;
    ElemType item;

    init_stack(&stack);



    printf("After init, stack1 length = %d\n", get_stack1_length(&stack));
    printf("After init, stack2 length = %d\n", get_stack2_length(&stack));
    printf("After init, is_stack1_empty = %d\n", is_stack1_empty(&stack));
    printf("After init, is_stack2_empty = %d\n", is_stack2_empty(&stack));


    /* 插入15个节点 */
    for (i = 0; i < 15; ++i) {
        memset(&item, 0, sizeof(item));
        item.id = i+1;
        snprintf(item.name, sizeof(item.name), "Stu_01_%02d", item.id);
        printf("push() item[%d] ret[%d]\n", i, push(&stack, &item, 1));
    }
    printf("\n");
    printf("After init, stack1 length = %d\n", get_stack1_length(&stack));
    printf("After init, stack2 length = %d\n", get_stack2_length(&stack));
    printf("After init, is_stack1_empty = %d\n", is_stack1_empty(&stack));
    printf("After init, is_stack2_empty = %d\n", is_stack2_empty(&stack));


    /* 插入10个节点 */
    for (i = 0; i < 10; ++i) {
        memset(&item, 0, sizeof(item));
        item.id = i+1;
        snprintf(item.name, sizeof(item.name), "Stu_02_%02d", item.id);
        printf("push() item[%d] ret[%d]\n", i, push(&stack, &item, 2));
    }
    printf("\n");
    printf("After init, stack1 length = %d\n", get_stack1_length(&stack));
    printf("After init, stack2 length = %d\n", get_stack2_length(&stack));
    printf("After init, is_stack1_empty = %d\n", is_stack1_empty(&stack));
    printf("After init, is_stack2_empty = %d\n", is_stack2_empty(&stack));

    printf("is_stack_full= %d\n", is_stack_full(&stack));


    memset(&item, 0, sizeof(item));
    get_stack1_top_item(&stack, &item);
    printf("After push, stack1 top item: Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);

    memset(&item, 0, sizeof(item));
    get_stack2_top_item(&stack, &item);
    printf("After push, stack2 top item: Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);



    printf("\n");
    /* 弹出25个节点 */
    for (i = 0; i < 25; ++i) {
        memset(&item, 0, sizeof(item));
        ret = pop(&stack, &item, 1);
        printf("pop() item[%d] ret[%d]\n", i, ret);
        if (ret == 0)
            printf("-- Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);
    }
    printf("After pop, stack1 length = %d\n", get_stack1_length(&stack));
    printf("After pop, stack2 length = %d\n", get_stack2_length(&stack));
    printf("After pop, is_stack1_empty = %d\n", is_stack1_empty(&stack));
    printf("After pop, is_stack2_empty = %d\n", is_stack2_empty(&stack));

    /* 弹出2个节点 */
    for (i = 0; i < 2; ++i) {
        memset(&item, 0, sizeof(item));
        ret = pop(&stack, &item, 2);
        printf("pop() item[%d] ret[%d]\n", i, ret);
        if (ret == 0)
            printf("-- Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);
    }
    printf("After pop, stack1 length = %d\n", get_stack1_length(&stack));
    printf("After pop, stack2 length = %d\n", get_stack2_length(&stack));
    printf("After pop, is_stack1_empty = %d\n", is_stack1_empty(&stack));
    printf("After pop, is_stack2_empty = %d\n", is_stack2_empty(&stack));



    clear_stack(&stack);
    clear_stack(&stack);
    clear_stack(&stack);

    printf("\n");
    printf("After clear, stack1 length = %d\n", get_stack1_length(&stack));
    printf("After clear, stack2 length = %d\n", get_stack2_length(&stack));
    printf("After clear, is_stack1_empty = %d\n", is_stack1_empty(&stack));
    printf("After clear, is_stack2_empty = %d\n", is_stack2_empty(&stack));


    /* 插入5个节点 */
    for (i = 0; i < 5; ++i) {
        memset(&item, 0, sizeof(item));
        item.id = i+1;
        snprintf(item.name, sizeof(item.name), "Stu_02_%02d", item.id);
        printf("push() item[%d] ret[%d]\n", i, push(&stack, &item, 2));

        snprintf(item.name, sizeof(item.name), "Stu_01_%02d", item.id);
        printf("push() item[%d] ret[%d]\n", i, push(&stack, &item, 1));
    }
    printf("\n");
    printf("After push, stack1 length = %d\n", get_stack1_length(&stack));
    printf("After push, stack2 length = %d\n", get_stack2_length(&stack));
    printf("After push, is_stack1_empty = %d\n", is_stack1_empty(&stack));
    printf("After push, is_stack2_empty = %d\n", is_stack2_empty(&stack));


    printf("\n");
    memset(&item, 0, sizeof(item));
    get_stack1_top_item(&stack, &item);
    printf("After push, stack1 top item: Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);

    memset(&item, 0, sizeof(item));
    get_stack2_top_item(&stack, &item);
    printf("After push, stack2 top item: Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);

    printf("is_stack_full= %d\n", is_stack_full(&stack));

    printf("\n");
    while (pop(&stack, &item, 1) != -1)
        printf("pop(): Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);
    while (pop(&stack, &item, 2) != -1)
        printf("pop(): Stu_id[%d], Stu_Name[%s]\n", item.id, item.name);

    printf("After pop, stack1 length = %d\n", get_stack1_length(&stack));
    printf("After pop, stack2 length = %d\n", get_stack2_length(&stack));
    printf("After pop, is_stack1_empty = %d\n", is_stack1_empty(&stack));
    printf("After pop, is_stack2_empty = %d\n", is_stack2_empty(&stack));


    return 0;
}
